using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Generic;
using System.Xml;


[Serializable]
public class LookupClass
{
    private string _name;
    private IList<LookupObject> _objects;

    public LookupClass()
        : this(string.Empty)
    {
    }

    public LookupClass(string className)
    {
        _name = className;
        _objects = new List<LookupObject>();
    }

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public IList<LookupObject> Objects
    {
        get { return _objects; }
    } 
}

[Serializable]
public class LookupObject
{
    private string _name = string.Empty;
    private int _typeCode;
    private string _displayName = string.Empty;
    private string _icon = string.Empty;
    private string _openUrl = string.Empty;
    private string _newUrl = string.Empty;
    private string _query = string.Empty;
    private IList<KeyValuePair<string, string>> _columns = new List<KeyValuePair<string, string>>();
    private string _orderByColumn = string.Empty;
    private bool _descendingOrder;

    public string NewUrl
    {
        get { return _newUrl; }
        set { _newUrl = value; }
    }

    public string OpenUrl
    {
        get { return _openUrl; }
        set { _openUrl = value; }
    }

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public int TypeCode
    {
        get { return _typeCode; }
        set { _typeCode = value; }
    }

    public string DisplayName
    {
        get { return _displayName; }
        set { _displayName = value; }
    }

    public string Icon
    {
        get { return _icon; }
        set { _icon = value; }
    }

    public string Query
    {
        get { return _query; }
        set { _query = value; }
    }

    public IList<KeyValuePair<string, string>> Columns
    {
        get { return _columns; }
        set { _columns = value; }
    }

    public string OrderByColumn
    {
        get { return _orderByColumn; }
        set { _orderByColumn = value; }
    }

    public bool DescendingOrder
    {
        get { return _descendingOrder; }
        set { _descendingOrder = value; }
    }
}

public class LookupClassLoader
{
    private CrmHelper _crmHelper;

	public LookupClassLoader(string orgName)
	{
		_crmHelper = new CrmHelper();
	}

    public LookupClassLoader(string server, string orgName)
    {
        _crmHelper = new CrmHelper(server, orgName);
    }

    public LookupClassLoader(CrmHelper crmHelper)
    {
        _crmHelper = crmHelper;
    }

    public CrmHelper CrmHelper
    {
        get { return _crmHelper; }
    }

    public LookupClass GetByName(string className)
    {
        LookupClass lkClass = null;
        XmlDataSource xdsLookupDialog = new XmlDataSource();
        xdsLookupDialog.DataFile = "~/App_Data/LookupDialog.xml";
        XmlDocument xdoc = xdsLookupDialog.GetXmlDocument();
        XmlElement lookupElement = xdoc.DocumentElement;
        XmlNode classNode = lookupElement.SelectSingleNode("class[@name=" + "'" + className + "'" + "]");

        if (classNode != null)
        {
            lkClass = PrepareLookupClass(classNode);
        }

        return lkClass;
    }

    private LookupClass PrepareLookupClass(XmlNode classNode)
    {
        LookupClass lkClass = new LookupClass();
        lkClass.Name = classNode.Attributes["name"].Value;
        XmlNodeList objNodeList = classNode.SelectNodes("object");
        foreach (XmlNode objNode in objNodeList)
        {
            LookupObject lkObject = new LookupObject();

            XmlAttribute nameAttr = objNode.Attributes["name"];
            if (nameAttr != null)
            {
                lkObject.Name = nameAttr.Value;
            }

            XmlAttribute iconAttr = objNode.Attributes["icon"];
            if (iconAttr != null)
            {
                lkObject.Icon = iconAttr.Value;
            }

            MetadataSdk.EntityMetadata entityMetadata = CrmHelper.GetEntityMetadata(lkObject.Name);

            XmlAttribute typecodeAttr = objNode.Attributes["typecode"];
            if (typecodeAttr != null)
            {
                lkObject.TypeCode = Convert.ToInt32(typecodeAttr.Value);
            }
            else if (entityMetadata != null)
            {
                lkObject.TypeCode = entityMetadata.ObjectTypeCode.Value;
            }

            XmlAttribute openUrlAttr = objNode.Attributes["openurl"];
            if (openUrlAttr != null)
            {
                lkObject.OpenUrl = string.Format(openUrlAttr.Value, CrmHelper.OrgName, "{0}", lkObject.TypeCode);
            }

            XmlAttribute newUrlAttr = objNode.Attributes["newurl"];
            if (newUrlAttr != null)
            {
                lkObject.NewUrl = string.Format(newUrlAttr.Value, CrmHelper.OrgName, lkObject.TypeCode);
            }

            XmlAttribute displaynameAttr = objNode.Attributes["displayname"];
            if (displaynameAttr != null)
            {
                lkObject.DisplayName = displaynameAttr.Value;
            }
            else if (entityMetadata != null)
            {
                lkObject.DisplayName = entityMetadata.DisplayName.UserLocLabel.Label;
            }

            XmlNode queryNode = objNode.SelectSingleNode("query");
            if (queryNode != null)
            {
                lkObject.Query = queryNode.InnerXml;
            }

            PrepareColumns(lkObject);

            lkClass.Objects.Add(lkObject);
        }

        return lkClass;
    }

    private void PrepareColumns(LookupObject lkObject)
    {
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(lkObject.Query);
        XmlElement fetchXmlNode = xmlDoc.DocumentElement;
        XmlNode entityNode = fetchXmlNode.SelectSingleNode("entity");
        XmlAttribute nameAttr = entityNode.Attributes["name"];
        string entityName = nameAttr.Value;

        MetadataSdk.EntityMetadata entityMetadata = CrmHelper.GetEntityMetadata(entityName);

        XmlNodeList attrNodeList = entityNode.SelectNodes("attribute");
        if (attrNodeList != null)
        {
            for (int I = 0; I < attrNodeList.Count; I++)
            {
                XmlNode attrNode = attrNodeList[I];
                XmlAttribute attr = attrNode.Attributes["name"];
                if (attr != null)
                {
                    string attrName = attr.Value;
                    foreach(MetadataSdk.AttributeMetadata attribute in entityMetadata.Attributes)
                    {
                        if (attribute.LogicalName == attrName)
                        {
                            KeyValuePair<string, string> column = new KeyValuePair<string, string>(attribute.LogicalName, attribute.DisplayName.UserLocLabel.Label);
                            lkObject.Columns.Add(column);
                        }
                    }
                }
            }
        }

        XmlNode orderNode = entityNode.SelectSingleNode("order");
        if (orderNode != null)
        {
            XmlAttribute orderAttr = orderNode.Attributes["attribute"];
            if (orderAttr != null)
            {
                lkObject.OrderByColumn = orderAttr.Value;
            }
            XmlAttribute orderDescAttr = orderNode.Attributes["descending"];
            if (orderDescAttr != null)
            {
                if (orderDescAttr.Value == "true" || orderDescAttr.Value == "1")
                {
                    lkObject.DescendingOrder = true;
                }
            }
        }
    }
}
